#include "stdafx.h"

namespace cpputils
{

serializer::property::property(serializer* SetSerializer)
	: Serializer(SetSerializer), Serialized(false), IsCompound(false)
{
}

serializer::property::~property()
{
	if (IsCompound && !uncaught_exception()) Serializer->end_compound();
}

serializer& serializer::property::get_serializer() const
{
	return *Serializer;
}

serializer::property::operator serializer&() const
{
	assert(!Serialized);
	Serializer->begin_compound();
	Serialized = true;
	IsCompound = true;
	return *Serializer;
}

serializer::serializer()
{
	ClassFactory = 0;
}

const class_factory* serializer::get_class_factory() const
{
	return ClassFactory;
}

void serializer::set_class_factory(const class_factory* Val)
{
	ClassFactory = Val;
}

bool serializer::is_saving() const
{
	return !is_loading();
}

void serializer::begin_property(const string& Name)
{
	new_property(Name);
	begin_compound();
}

void serializer::end_property()
{
	end_compound();
}

text_serializer::text_serializer()
{
	Fmt.set_delimiters("=,\"\'{}");
}

void text_serializer::load(const string& Filename)
{
	File.reset(Filename, "r");
	Fmt.set_file(File);
	Fmt.set_reading();
	First = true;
	Indent = 0;
}

void text_serializer::save(const string& Filename)
{
	File.reset(Filename, "w");
	Fmt.set_file(File);
	Fmt.set_writing();
	First = true;
	Indent = 0;
}

void text_serializer::close()
{
	if (Indent != 0) throw runtime_error("Serialization format error");
	if (is_loading()) Fmt.finish();
	File.reset();
}

bool text_serializer::is_loading() const
{
	return Fmt.is_reading();
}

bool text_serializer::eof()
{
	return Fmt.eof();
}

void text_serializer::new_property(const string& Name)
{
	if (!First) Fmt << ',';
	First = false;
	if (!Name.empty()) Fmt << '\n' << string(Indent, '\t') << Name << '=';
}

void text_serializer::begin_compound()
{
	First = true;
	Indent++;
	Fmt << '{';
}

void text_serializer::end_compound()
{
	Fmt << '}';
	Indent--;
	First = false;
}

void text_serializer::serialize_object(bool& V)
{
	if (is_loading())
	{
		string S;
		Fmt >> S;
		if (S == "true") V = true;
		else if (S == "false") V = false;
		else Fmt.format_error("Invalid boolean value");
	}
	else
		if (V) Fmt << "true";
		else Fmt << "false";
}

void text_serializer::serialize_object(int& V)
{
	Fmt >> V;
}

void text_serializer::serialize_object(unsigned int& V)
{
	Fmt >> V;
}

void text_serializer::serialize_object(short& V)
{
	Fmt >> V;
}

void text_serializer::serialize_object(unsigned short& V)
{
	Fmt >> V;
}

void text_serializer::serialize_object(long& V)
{
	Fmt >> V;
}

void text_serializer::serialize_object(unsigned long& V)
{
	Fmt >> V;
}

void text_serializer::serialize_object(long long& V)
{
	Fmt >> V;
}

void text_serializer::serialize_object(unsigned long long& V)
{
	Fmt >> V;
}

void text_serializer::serialize_object(float& V)
{
	Fmt >> V;
}

void text_serializer::serialize_object(double& V)
{
	Fmt >> V;
}

void text_serializer::serialize_object(string& V)
{
	Fmt << '"' >> V << '"';
}

}
